{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 详细学习见 https://www.bilibili.com/video/BV11r1FBWE9B/\n",
    "\n",
    "\n",
    "| 语法                              | 主要用途                                                     | 编译期检查                           | 失败时行为                                                   | 典型场景                                                     | 风险与建议                                                   |\n",
    "| --------------------------------- | ------------------------------------------------------------ | ------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n",
    "| `static_cast<T>`                  | 有理有据的类型转换：数值扩大/缩窄、显式构造、指针/引用的上行或下行转换（受限） | 中等：检查父子关系、禁止无关类型转换 | 编译失败（若不成立）；运行期无额外检查                       | 整型与浮点转换；`void*` ↔ 有类型指针；类层次结构中的上行转换 | 下行转换不会做 RTTI 检查，错误转换行为未定义；可搭配断言或 `dynamic_cast` 验证 |\n",
    "| `dynamic_cast<T>`                 | 运行期带 RTTI 的安全下行转换                                 | 高：仅适用于含虚函数的多态类型       | 成功返回指针/引用；失败时指针得 `nullptr`，引用抛 `std::bad_cast` | 基类指针/引用转换为派生类指针/引用，实现「问询类型」模式     | 需要虚函数支持；引入 RTTI 和潜在的运行期开销；不适用于 `union` 或无多态的结构 |\n",
    "| `const_cast<T>`                   | 增删顶层 `const` / `volatile` 限定符                         | 低：只检查限定符合法性               | 行为依赖实际对象是否可变；违反则未定义                       | 为与旧 API 交互移除 const；调用只接受非常量指针的 C API      | 切勿对本应为常量的对象去 const 后再写；常与 `mutable` 或 API 重构配合 |\n",
    "| `reinterpret_cast<T>`             | 重新解释底层位模式，进行与类型系统无关的转换                 | 极低：几乎不检查                     | 行为往往未定义或非移植，取决于实现                           | 将整数视为指针、指针互转、访问硬件寄存器、序列化/反序列化底层字节 | 仅在需要逐位操作或底层平台接口时使用；配合 `std::bit_cast`（C++20）更安全 |\n",
    "| `const Type(expr)`（函数式 cast） | 与 C 风格相同：按顺序尝试 `const_cast`→`static_cast`→`reinterpret_cast` | 低：逐步尝试，可能绕过安全限制       | 行为取决于最终选择的 cast；错误时未定义                      | 调用构造函数样式转换                                         | 建议使用显式新式 cast 以便读者理解意图，对编译器也更友好     |\n",
    "| `(Type)expr`（C 风格）            | 同上，兼容 C 的旧语法                                        | 低                                   | 同上                                                         | 历史代码或需要兼容 C 接口                                    | 不建议在现代 C++ 中继续使用，难以阅读，容易隐藏危险转换      |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. **优先使用现代 cast**：`static_cast`、`dynamic_cast`、`const_cast`、`reinterpret_cast` 都能通过名字传达意图，便于代码审查，也利于工具做静态分析。\n",
    "2. **降低对 `reinterpret_cast` 的依赖**：若目标是“按位复制”而非“重解释”，优先考虑 `std::bit_cast`（C++20）或序列化库。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# static_cast：数值转换与安全的上行/下行转换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- 数值类型转换 ---\n",
      "42 / 5.0 = 8.4\n",
      "\n",
      "--- 类层次结构转换 ---\n",
      "Derived::greet()\n",
      "Derived 支持的独有操作\n"
     ]
    }
   ],
   "source": [
    "#include <iostream>\n",
    "\n",
    "struct Base {\n",
    "  virtual ~Base() = default;\n",
    "  virtual void greet() const { std::cout << \"Base::greet()\\n\"; }\n",
    "};\n",
    "\n",
    "struct Derived : Base {\n",
    "  void greet() const override { std::cout << \"Derived::greet()\\n\"; }\n",
    "  void derived_only() const { std::cout << \"Derived 支持的独有操作\\n\"; }\n",
    "};\n",
    "\n",
    "{\n",
    "  std::cout << \"--- 数值类型转换 ---\\n\";\n",
    "  int i = 42;\n",
    "  double d = static_cast<double>(i) / 5.0;\n",
    "  std::cout << \"42 / 5.0 = \" << d << '\\n';\n",
    "\n",
    "  std::cout << \"\\n--- 类层次结构转换 ---\\n\";\n",
    "  Derived derived;\n",
    "  Base* base_ptr = static_cast<Base*>(&derived); // 上行转换安全\n",
    "  base_ptr->greet();\n",
    "\n",
    "  // 使用 static_cast 执行已知安全的下行转换（要求开发者保证类型正确）\n",
    "  Derived* down_ptr = static_cast<Derived*>(base_ptr);\n",
    "  down_ptr->derived_only();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`static_cast` 在指针转换上做了严格的类型检查，只允许以下几类安全的指针转换：\n",
    "\n",
    "- 在同一继承体系中的上行/下行（有相应的限制）；\n",
    "- `void*` 与任意对象指针之间；\n",
    "- `nullptr` 与任意对象指针之间；\n",
    "- 去掉 `const`/`volatile`（其实要配合 `const_cast`）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# dynamic_cast：带 RTTI 的安全下行转换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "#include <memory>\n",
    "#include <typeinfo>\n",
    "\n",
    "struct Shape {\n",
    "  virtual ~Shape() = default;\n",
    "  virtual void draw() const { std::cout << \"Shape::draw()\\n\"; }\n",
    "};\n",
    "\n",
    "struct Circle : Shape {\n",
    "  void draw() const override { std::cout << \"Circle::draw()\\n\"; }\n",
    "  double radius = 1.0;\n",
    "};\n",
    "\n",
    "struct Rectangle : Shape {\n",
    "  void draw() const override { std::cout << \"Rectangle::draw()\\n\"; }\n",
    "};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "成功识别 Circle，半径 = 1\n",
      "不是 Circle，RTTI 类型 = 9Rectangle\n"
     ]
    }
   ],
   "source": [
    "void try_cast(Shape* shape) {\n",
    "  if (auto* circle = dynamic_cast<Circle*>(shape)) {\n",
    "    std::cout << \"成功识别 Circle，半径 = \" << circle->radius << '\\n';\n",
    "  } else {\n",
    "    std::cout << \"不是 Circle，RTTI 类型 = \" << typeid(*shape).name() << '\\n';\n",
    "  }\n",
    "}\n",
    "\n",
    "{\n",
    "  Circle c;\n",
    "  Rectangle r;\n",
    "\n",
    "  Shape* shape1 = &c;\n",
    "  Shape* shape2 = &r;\n",
    "\n",
    "  try_cast(shape1);\n",
    "  try_cast(shape2);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# const_cast：在确知对象可写时移除 const"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "调用前 mutable_value = 100\n",
      "legacy_api 修改数据...\n",
      "调用后 mutable_value = 2025\n",
      "\n",
      "⚠️ 以下操作演示错误用法，结果未定义 ---\n",
      "尝试写入真正的常量对象会导致未定义行为，示例中不会执行写操作。\n"
     ]
    }
   ],
   "source": [
    "#include <iostream>\n",
    "\n",
    "void legacy_api(int* data) {\n",
    "  std::cout << \"legacy_api 修改数据...\\n\";\n",
    "  *data = 2025;\n",
    "}\n",
    "\n",
    "{\n",
    "  int mutable_value = 100;\n",
    "  const int* view = &mutable_value; // 假设收到一个只读视图\n",
    "\n",
    "  std::cout << \"调用前 mutable_value = \" << mutable_value << '\\n';\n",
    "  legacy_api(const_cast<int*>(view));\n",
    "  std::cout << \"调用后 mutable_value = \" << mutable_value << '\\n';\n",
    "\n",
    "  std::cout << \"\\n⚠️ 以下操作演示错误用法，结果未定义 ---\\n\";\n",
    "  const int constant_value = 7;\n",
    "  const int* constant_view = &constant_value;\n",
    "  int* illegal_ptr = const_cast<int*>(constant_view);\n",
    "  std::cout << \"尝试写入真正的常量对象会导致未定义行为，示例中不会执行写操作。\\n\";\n",
    "  (void)illegal_ptr; // 避免未使用警告\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# reinterpret_cast：重新解释底层位模式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PacketHeader 的字节序： 0x34 0x12 0xff 0x00\n",
      "指针转换为整数 = 0x7ffd15a85930\n",
      "还原后的 header.id = 0x1234, header.length = 0xff\n"
     ]
    }
   ],
   "source": [
    "//  reinterpret_cast 直接处理底层位模式，非常依赖平台与对象布局，应只在确实需要的低层场景使用，并遵守严格别名与对齐规则。\n",
    "\n",
    "#include <iostream>\n",
    "#include <cstdint>\n",
    "#include <iomanip>\n",
    "\n",
    "struct PacketHeader {\n",
    "  std::uint16_t id;\n",
    "  std::uint16_t length;\n",
    "};\n",
    "\n",
    "{\n",
    "  PacketHeader header{0x1234, 0x00FF};\n",
    "  std::uint8_t* raw_bytes = reinterpret_cast<std::uint8_t*>(&header);\n",
    "\n",
    "  std::cout << \"PacketHeader 的字节序：\" << std::hex << std::setfill('0');\n",
    "  for (std::size_t i = 0; i < sizeof(PacketHeader); ++i) {\n",
    "    std::cout << \" 0x\" << std::setw(2) << static_cast<int>(raw_bytes[i]);\n",
    "  }\n",
    "  std::cout << std::dec << '\\n';\n",
    "\n",
    "  // 将指针转成整数再还原，仅作演示\n",
    "  std::uintptr_t raw_address = reinterpret_cast<std::uintptr_t>(&header);\n",
    "  std::cout << \"指针转换为整数 = 0x\" << std::hex << raw_address << std::dec << '\\n';\n",
    "\n",
    "  PacketHeader* restored = reinterpret_cast<PacketHeader*>(raw_address);\n",
    "  std::cout << \"还原后的 header.id = 0x\" << std::hex << restored->id\n",
    "            << \", header.length = 0x\" << restored->length << std::dec << '\\n';\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
